OPC Studio User's Guide and Reference
Examples - OPC XML-DA - Browse nodes recursively

.NET

// This example shows how to recursively browse the nodes in the OPC XML-DA address space.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using System.Diagnostics;
using OpcLabs.EasyOpc;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.AddressSpace;
using OpcLabs.EasyOpc.OperationModel;

namespace DocExamples.DataAccess.Xml
{
    class BrowseNodes
    {
        public static void RecursiveXml()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();

            // Instantiate the client object.
            var client = new EasyDAClient();

            _branchCount = 0;
            _leafCount = 0;

            try
            {
                BrowseFromNode(client, "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx", "");
            }
            catch (OpcException opcException)
            {
                Console.WriteLine("*** Failure: {0}", opcException.GetBaseException().Message);
                return;
            }

            stopwatch.Stop();
            Console.WriteLine("Browsing has taken (milliseconds): {0}", stopwatch.ElapsedMilliseconds);
            Console.WriteLine("Branch count: {0}", _branchCount);
            Console.WriteLine("Leaf count: {0}", _leafCount);
        }

        private static void BrowseFromNode(
            EasyDAClient client,
            ServerDescriptor serverDescriptor,
            DANodeDescriptor parentNodeDescriptor)
        {
            Debug.Assert(client != null);
            Debug.Assert(serverDescriptor != null);
            Debug.Assert(parentNodeDescriptor != null);

            // Obtain all node elements under parentNodeDescriptor
            var browseParameters = new DABrowseParameters();    // no filtering whatsoever
            DANodeElementCollection nodeElementCollection =
                client.BrowseNodes(serverDescriptor, parentNodeDescriptor, browseParameters);
            // Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for 
            // it, here omitted for brevity.

            foreach (DANodeElement nodeElement in nodeElementCollection)
            {
                Debug.Assert(nodeElement != null);

                Console.WriteLine(nodeElement);

                // If the node is a branch, browse recursively into it.
                if (nodeElement.IsBranch)
                {
                    _branchCount++;
                    BrowseFromNode(client, serverDescriptor, nodeElement);
                }
                else
                {
                    _leafCount++;
                }
            }
        }

        private static int _branchCount;
        private static int _leafCount;
    }
}
' This example shows how to recursively browse the nodes in the OPC XML-DA address space.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports OpcLabs.EasyOpc
Imports OpcLabs.EasyOpc.DataAccess
Imports OpcLabs.EasyOpc.DataAccess.AddressSpace
Imports OpcLabs.EasyOpc.OperationModel

Namespace DataAccess.Xml
    Partial Friend Class BrowseNodes

        Shared Sub RecursiveXml()
            Dim stopwatch = New Stopwatch()
            stopwatch.Start()

            Dim client = New EasyDAClient()
            _branchCount = 0
            _leafCount = 0

            Try
                BrowseFromNode(client, "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx", "")
            Catch opcException As OpcException
                Console.WriteLine("*** Failure: {0}", opcException.GetBaseException().Message)
                Exit Sub
            End Try

            stopwatch.Stop()
            Console.WriteLine("Browsing has taken (milliseconds): {0}", stopwatch.ElapsedMilliseconds)
            Console.WriteLine("Branch count: {0}", _branchCount)
            Console.WriteLine("Leaf count: {0}", _leafCount)
        End Sub

        Private Shared Sub BrowseFromNode( _
            client As EasyDAClient,
            serverDescriptor As ServerDescriptor,
            parentNodeDescriptor As DANodeDescriptor)

            Debug.Assert(client IsNot Nothing)
            Debug.Assert(serverDescriptor IsNot Nothing)
            Debug.Assert(parentNodeDescriptor IsNot Nothing)

            ' Obtain all node elements under parentNodeDescriptor
            Dim browseParameters = New DABrowseParameters() ' no filtering whatsoever
            Dim nodeElementCollection As DANodeElementCollection =
                client.BrowseNodes(serverDescriptor, parentNodeDescriptor, browseParameters)
            ' Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for 
            ' it, here omitted for brevity.

            For Each nodeElement As DANodeElement In nodeElementCollection
                Debug.Assert(nodeElement IsNot Nothing)

                Console.WriteLine(nodeElement)

                ' If the node is a branch, browse recursively into it.
                If nodeElement.IsBranch Then
                    _branchCount += 1
                    BrowseFromNode(client, serverDescriptor, nodeElement)
                Else
                    _leafCount += 1
                End If
            Next nodeElement
        End Sub

        Private Shared _branchCount As Integer
        Private Shared _leafCount As Integer
    End Class
End Namespace

COM

// This example shows how to recursively browse the nodes in the OPC XML-DA address space.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in Object Pascal (Delphi) on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-OP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

type
  TBrowseNodes = class
    BranchCount: Integer;
    LeafCount: Integer;
    procedure BrowseFromNode(
      Client: OpcLabs_EasyOpcClassic_TLB._EasyDAClient;
      ServerDescriptor: _ServerDescriptor;
      ParentNodeDescriptor:  _DANodeDescriptor);
  end;

procedure TBrowseNodes.BrowseFromNode(
      Client: OpcLabs_EasyOpcClassic_TLB._EasyDAClient;
      ServerDescriptor: _ServerDescriptor;
      ParentNodeDescriptor: _DANodeDescriptor);
var
  BrowseParameters: _DABrowseParameters;
  Count: Cardinal;
  Element: OleVariant;
  NodeElement: _DANodeElement;
  NodeElementEnumerator: IEnumVariant;
  NodeElements: _DANodeElementCollection;
begin
  // Obtain all node elements under ParentNodeDescriptor
  BrowseParameters := CoDABrowseParameters.Create;  // no filtering whatsover
  NodeElements := Client.BrowseNodes(
    ServerDescriptor,
    ParentNodeDescriptor,
    BrowseParameters);
  // Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for 
  // it, here omitted for brevity.

  NodeElementEnumerator := NodeElements.GetEnumerator;
  while (NodeElementEnumerator.Next(1, Element, Count) = S_OK) do
  begin
    NodeElement := IUnknown(Element) as _DANodeElement;
    WriteLn(NodeElement.ToString);

    // If the node is a branch, browse recursively into it.
    if NodeElement.IsBranch then
    begin
      BranchCount := BranchCount + 1;
      BrowseFromNode(Client, ServerDescriptor, NodeElement.ToDANodeDescriptor);
    end
    else
      LeafCount := LeafCount + 1;
  end;
end;

class procedure BrowseNodes.RecursiveXml;
var
  BeginTime: Cardinal;
  BrowseNodes: TBrowseNodes;
  Client: OpcLabs_EasyOpcClassic_TLB._EasyDAClient;
  EndTime: Cardinal;
  ServerDescriptor: _ServerDescriptor;
  NodeDescriptor: _DANodeDescriptor;
begin
  BrowseNodes := TBrowseNodes.Create;
  BrowseNodes.BranchCount := 0;
  BrowseNodes.LeafCount := 0;

  BeginTime := Ticks;

  ServerDescriptor := CoServerDescriptor.Create;
  ServerDescriptor.UrlString := 'http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx';

  NodeDescriptor := CoDANodeDescriptor.Create;
  NodeDescriptor.ItemId := '';

  // Instantiate the client object
  Client := CoEasyDAClient.Create;

  try
    BrowseNodes.BrowseFromNode(
      Client,
      ServerDescriptor,
      NodeDescriptor);
  except
    on E: EOleException do
    begin
      WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
      Exit;
    end;
  end;

  EndTime := Ticks;

  WriteLn;
  WriteLn('Browsing has taken (milliseconds): ', (endTime - beginTime) * 1000);
  WriteLn('Branch count: ', BrowseNodes.BranchCount);
  WriteLn('Leaf count: ', BrowseNodes.LeafCount);
end;
// This example shows how to recursively browse the nodes in the OPC XML-DA address space.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in PHP on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-PHP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

$beginTime = microtime(true);
$branchCount = 0;
$leafCount = 0;

$ServerDescriptor = new COM("OpcLabs.EasyOpc.ServerDescriptor");
$ServerDescriptor->UrlString = "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx";

$NodeDescriptor = new COM("OpcLabs.EasyOpc.DataAccess.DANodeDescriptor");
$NodeDescriptor->ItemID = "";

// Instantiate the client object.
$Client = new COM("OpcLabs.EasyOpc.DataAccess.EasyDAClient");

try
{
    BrowseFromNode($Client, $ServerDescriptor, $NodeDescriptor);
}
catch (com_exception $e)
{
    printf("*** Failure: %s\n", $e->getMessage());
    Exit();
}

$endTime = microtime(true);

printf("\n");
printf("Browsing has taken (milliseconds): : %f\n", ($endTime - $beginTime) * 1000);
printf("Branch count: %d\n", $branchCount);
printf("Leaf count: %d\n", $leafCount);


function BrowseFromNode($Client, $ServerDescriptor, $ParentNodeDescriptor) : void
{
    global $branchCount, $leafCount;

    // Obtain all node elements under ParentNodeDescriptor
    $BrowseParameters = new COM("OpcLabs.EasyOpc.DataAccess.DABrowseParameters"); // no filtering whatsoever
    $NodeElementCollection = $Client->BrowseNodes($ServerDescriptor, $ParentNodeDescriptor,$BrowseParameters);
    // Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for 
    //it, here omitted for brevity.

    foreach ($NodeElementCollection as $NodeElement)
    {
        printf("%s\n", $NodeElement);

        // If the node is a branch, browse recursively into it.
        if ($NodeElement->IsBranch)
        {
            $branchCount = $branchCount + 1;
            BrowseFromNode($Client, $ServerDescriptor, $NodeElement->ToDANodeDescriptor());
        }
        else
        {
            $leafCount = $leafCount + 1;
        }
    }
}
Rem This example shows how to recursively browse the nodes in the OPC XML-DA address space.
Rem
REM Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
REM OPC client and subscriber examples in Visual Basic on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VB .
REM Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
REM a commercial license in order to use Online Forums, and we reply to every post.

'Public branchCount As Integer
'Public leafCount As Integer

Private Sub BrowseNodes_RecursiveXml_Command_Click()
    OutputText = ""
    branchCount = 0
    leafCount = 0
    Dim beginTime: beginTime = Timer
        
    Dim serverDescriptor As New serverDescriptor
    serverDescriptor.UrlString = "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx"
    
    Dim NodeDescriptor As New DANodeDescriptor
    NodeDescriptor.ItemId = ""
    
    ' Instantiate the client object
    Dim client As New EasyDAClient

    On Error Resume Next
        BrowseFromNode client, serverDescriptor, NodeDescriptor
    If Err.Number <> 0 Then
        OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf
        Exit Sub
    End If
    On Error GoTo 0

    Dim endTime: endTime = Timer
    
    OutputText = OutputText & vbCrLf
    OutputText = OutputText & "Browsing has taken (milliseconds): " & (endTime - beginTime) * 1000 & vbCrLf
    OutputText = OutputText & "Branch count: " & branchCount & vbCrLf
    OutputText = OutputText & "Leaf count: " & leafCount & vbCrLf
End Sub

Public Sub BrowseFromNode(client, serverDescriptor, ParentNodeDescriptor)
    ' Obtain all node elements under ParentNodeDescriptor
    Dim BrowseParameters As New DABrowseParameters
    Dim NodeElementCollection As DANodeElementCollection
    Set NodeElementCollection = client.BrowseNodes(serverDescriptor, ParentNodeDescriptor, BrowseParameters)
    ' Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for
    ' it, here omitted for brevity.

    Dim NodeElement: For Each NodeElement In NodeElementCollection
        OutputText = OutputText & NodeElement & vbCrLf
        
        ' If the node is a branch, browse recursively into it.
        If NodeElement.IsBranch Then
            branchCount = branchCount + 1
            BrowseFromNode client, serverDescriptor, NodeElement.ToDANodeDescriptor
        Else
            leafCount = leafCount + 1
        End If
    Next
End Sub
Rem This example shows how to recursively browse the nodes in the OPC XML-DA address space.
Rem
Rem Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
Rem OPC client and subscriber examples in VBScript on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBScript .
Rem Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
Rem a commercial license in order to use Online Forums, and we reply to every post.

Option Explicit

Dim beginTime: beginTime = Timer
Dim branchCount: branchCount = 0
Dim leafCount: leafCount = 0

Dim ServerDescriptor: Set ServerDescriptor = CreateObject("OpcLabs.EasyOpc.ServerDescriptor")
ServerDescriptor.UrlString = "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx"

Dim NodeDescriptor: Set NodeDescriptor = CreateObject("OpcLabs.EasyOpc.DataAccess.DANodeDescriptor")
NodeDescriptor.ItemID = ""

Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
On Error Resume Next
BrowseFromNode Client, ServerDescriptor, NodeDescriptor
If Err.Number <> 0 Then
    WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description
    WScript.Quit
End If
On Error Goto 0

Dim endTime: endTime = Timer

WScript.Echo ""
WScript.Echo "Browsing has taken (milliseconds): " & (endTime - beginTime) * 1000
WScript.Echo "Branch count: " & branchCount
WScript.Echo "Leaf count: " & leafCount


Sub BrowseFromNode(Client, ServerDescriptor, ParentNodeDescriptor)
    ' Obtain all node elements under ParentNodeDescriptor
    Dim BrowseParameters: Set BrowseParameters = CreateObject("OpcLabs.EasyOpc.DataAccess.DABrowseParameters")
    Dim NodeElementCollection: Set NodeElementCollection = Client.BrowseNodes(serverDescriptor, parentNodeDescriptor, browseParameters)
    ' Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for 
    ' it, here omitted for brevity.

    Dim NodeElement: For Each NodeElement In NodeElementCollection
        WScript.Echo NodeElement
        
        ' If the node is a branch, browse recursively into it.
        If NodeElement.IsBranch Then
            branchCount = branchCount + 1
            BrowseFromNode Client, ServerDescriptor, NodeElement.ToDANodeDescriptor
        Else
            leafCount = leafCount + 1
        End If
    Next

End Sub

Python

# This example shows how to recursively browse the nodes in the OPC XML-DA address space.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import timeit

# Import .NET namespaces.
from OpcLabs.EasyOpc import *
from OpcLabs.EasyOpc.DataAccess import *
from OpcLabs.EasyOpc.OperationModel import *


def browseFromNode(client, serverDescriptor, parentNodeDescriptor):
    global branchCount
    global leafCount

    assert client is not None
    assert serverDescriptor is not None
    assert parentNodeDescriptor is not None

    # Obtain all node elements under parentNodeDescriptor.
    browseParameters = DABrowseParameters() # no filtering whatsoever
    nodeElementCollection = client.BrowseNodes(serverDescriptor, parentNodeDescriptor, browseParameters)
    # BrowseNodes(...) may also throw OpcException; here it is handled by the caller.

    for nodeElement in nodeElementCollection:
        assert nodeElement is not None
        print(nodeElement)

        # If the node is a branch, browse recursively into it.
        if nodeElement.IsBranch:
            branchCount = branchCount + 1
            browseFromNode(client, serverDescriptor, DANodeDescriptor(nodeElement))
        else:
            leafCount = leafCount + 1


beginTime = timeit.default_timer()

# Instantiate the client object.
client = EasyDAClient()
branchCount = 0
leafCount = 0

try:
    browseFromNode(client,
                   ServerDescriptor('http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx'),
                   DANodeDescriptor(''))
except OpcException as opcException:
    print('*** Failure: ' + opcException.GetBaseException().Message)
    exit()

endTime = timeit.default_timer()
print()
print('Browsing has taken (milliseconds): ',(endTime - beginTime)*1000)
print('Branch count: ', branchCount);
print('Leaf count: ', leafCount);

 

QuickOPC supports OPC XML-DA also on Linux and macOS.
See Also

Examples - Client OPC Data Access

Concepts